package com.bbs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bbs.dto.*;
import com.bbs.exception.BusinessException;
import com.bbs.feign.MessageClient;
import com.bbs.mapper.UserFriendshipMapper;
import com.bbs.mapper.UserMapper;
import com.bbs.pojo.Message;
import com.bbs.pojo.Result;
import com.bbs.pojo.UserFriendship;
import com.bbs.pojo.UserPrincipal;
import com.bbs.pojo.dto.MessageDto;
import com.bbs.pojo.dto.message.FriendApplicationMessageContent;
import com.bbs.pojo.dto.message.SystemMessageContent;
import com.bbs.service.UserFriendService;
import com.bbs.utils.Constants;
import com.bbs.utils.MessageSender;
import com.bbs.utils.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class UserFriendshipServiceImpl extends ServiceImpl<UserFriendshipMapper, UserFriendship> implements UserFriendService {
    @Autowired
    UserMapper userMapper;
    @Autowired
    UserFriendshipMapper userFriendshipMapper;
    @Autowired
    MessageSender messageSender;
    @Autowired
    MessageClient messageClient;

    @Override
    public List<FriendGroupDto> getGroupedFriendList(String userId) {
        UserFriendship friendship = new UserFriendship();
        friendship.setUserId(userId);
        QueryWrapper<UserFriendship> queryWrapper = new QueryWrapper<>(friendship);
        List<UserFriendship> friends = list(queryWrapper);

        //按 好友分组 分组
        Map<String, List<FriendDto>> groupedFriendDtos = new HashMap<>();
        String friendGroup;
        for (UserFriendship friend : friends) {
            //为null 默认为 "我的好友"分组
            friendGroup = friend.getFriendGroup();
            if (friendGroup == null) {
                friendGroup = "我的好友";
            }

            List<FriendDto> friendDtos = groupedFriendDtos.computeIfAbsent(friendGroup, k -> new ArrayList<>());

            FriendDto friendDto = new FriendDto();
            friendDto.setFriendGroup(friendGroup);
            friendDto.setFriendUsername(userMapper.getUsernameById(friend.getFriendId()));
            friendDto.setFriendUserId(friend.getFriendId());

            friendDtos.add(friendDto);
        }

        List<FriendGroupDto> friendGroupDtos = new ArrayList<>();
        for (Map.Entry<String, List<FriendDto>> entry : groupedFriendDtos.entrySet()) {
            FriendGroupDto friendGroupDto = new FriendGroupDto();
            friendGroupDto.setName(entry.getKey());
            friendGroupDto.setFriends(entry.getValue());
            friendGroupDtos.add(friendGroupDto);
        }
        return friendGroupDtos;
    }

    @Override
    public List<String> getFriendGroupNames(String userId) {
        return userFriendshipMapper.getFriendGroupsByUser(userId);
    }

    @Override
    public boolean checkIsFriend(String userId1, String userId2) {
        UserFriendship userFriendship = new UserFriendship();
        userFriendship.setUserId(userId1);
        userFriendship.setFriendId(userId2);
        return userFriendshipMapper.exists(new QueryWrapper<>(userFriendship));
    }

    @Override
    @Transactional
    public boolean deleteFriend(String userId1, String userId2) {
        UserFriendship userFriendship = new UserFriendship();
        userFriendship.setUserId(userId1);
        userFriendship.setFriendId(userId2);
        boolean flag = remove(new QueryWrapper<>(userFriendship));
        userFriendship.setUserId(userId2);
        userFriendship.setFriendId(userId1);
        flag |= remove(new QueryWrapper<>(userFriendship));
        return flag;
    }

    @Override
    public boolean renameFriendGroup(String userId, String friendGroupName, String newFriendGroupName) {
        UserFriendship userFriendship = new UserFriendship();
        userFriendship.setUserId(userId);
        userFriendship.setFriendGroup(newFriendGroupName);

        UserFriendship userFriendship1 = new UserFriendship();
        userFriendship1.setUserId(userId);
        userFriendship1.setFriendGroup(friendGroupName);

        return update(userFriendship, new UpdateWrapper<>(userFriendship1));
    }

    @Override
    public boolean updateFriendInfo(String userId, UpdateFriendInfoRequest updateFriendInfoRequest) {
        UserFriendship userFriendship = new UserFriendship();
        userFriendship.setUserId(userId);
        userFriendship.setFriendId(updateFriendInfoRequest.getFriendUserId());
        userFriendship.setFriendGroup(updateFriendInfoRequest.getFriendGroupName());

        UserFriendship userFriendship1 = new UserFriendship();
        userFriendship1.setUserId(userId);
        userFriendship1.setFriendId(updateFriendInfoRequest.getFriendUserId());

        return update(userFriendship, new UpdateWrapper<>(userFriendship1));
    }

    @Override
    public boolean applyNewFriend(UserPrincipal applicant, ApplyNewFriendRequest applyNewFriendRequest) {
        String friendUserId = userMapper.getIdByUsername(applyNewFriendRequest.getFriendUsername());
        if(friendUserId == null) {
            throw new BusinessException("用户(username:" + applyNewFriendRequest.getFriendUsername() + ") 不存在");
        }

        if(friendUserId.equals(applicant.getUserId())){
            throw new BusinessException("不能添加自己为好友");
        }

        if(checkIsFriend(applicant.getUserId(), friendUserId)){
            throw new BusinessException("不可重复添加好友");
        }

        //TODO：删除旧的申请

        FriendApplicationMessageContent messageContent = new FriendApplicationMessageContent();
        messageContent.setApplicationMessage(applyNewFriendRequest.getApplicationMessage());
        messageContent.setFriendGroupName(applyNewFriendRequest.getFriendGroupName());
        messageContent.setApplicantUsername(applicant.getUsername());

        //发送申请
        messageSender.send(friendUserId, applicant.getUserId(), messageContent);

        return true;
    }

    //TODO: 分布式事务
    @Override
    @Transactional
    public boolean acceptNewFriend(String userId, AcceptNewFriendRequest acceptNewFriendRequest) {
        String messageId = acceptNewFriendRequest.getFriendApplicationMessageId();
        MessageDto messageDto = getMessageDtoHelper(messageId, userId);

        FriendApplicationMessageContent content = (FriendApplicationMessageContent) messageDto.getContent();
        if(content == null){
            throw new BusinessException("消息格式错误");
        }

        String friendGroupName = acceptNewFriendRequest.getFriendGroupName();

        UserFriendship userFriendship = new UserFriendship();
        userFriendship.setUserId(userId);
        userFriendship.setFriendId(messageDto.getSenderId());
        userFriendship.setFriendGroup(acceptNewFriendRequest.getFriendGroupName());
        userFriendshipMapper.insert(userFriendship);

        userFriendship.setUserId(messageDto.getSenderId());
        userFriendship.setFriendId(userId);
        userFriendship.setFriendGroup(content.getFriendGroupName());
        userFriendshipMapper.insert(userFriendship);

        //删除消息
        Result<Object> removeResult = messageClient.removeMessage(messageId);
        if(!Objects.equals(removeResult.getCode(), Constants.SUCCESS_CODE)){
            throw new BusinessException("消息删除失败");
        }

        //通知申请者已被同意
        SystemMessageContent messageContent = new SystemMessageContent();
        String username = userMapper.getUsernameById(userId);
        messageContent.setText(username + "同意了您的好友申请");
        messageSender.send(messageDto.getSenderId(), userId, messageContent);
        return true;
    }

    @Override
    public boolean rejectNewFriend(String userId, String messageId) {
        MessageDto messageDto = getMessageDtoHelper(messageId, userId);

        FriendApplicationMessageContent content = (FriendApplicationMessageContent) messageDto.getContent();
        if(content == null){
            throw new BusinessException("消息格式错误");
        }

        //删除消息
        Result<Object> removeResult = messageClient.removeMessage(messageId);
        if(!Objects.equals(removeResult.getCode(), Constants.SUCCESS_CODE)){
            throw new BusinessException("消息删除失败");
        }

        //将通知申请者被拒绝
        SystemMessageContent messageContent = new SystemMessageContent();
        String username = userMapper.getUsernameById(userId);
        messageContent.setText(username + "拒绝了您的好友申请");
        messageSender.send(messageDto.getSenderId(), userId, messageContent);

        return true;
    }

    private MessageDto getMessageDtoHelper(String messageId, String receiverId){
        Result<Object> result = messageClient.getMessage(messageId);

        LinkedHashMap<String, Object> messageMap = null;
        if(result != null){
            messageMap = (LinkedHashMap<String, Object>) result.getData();
        }

        MessageDto messageDto = null;
        if(messageMap != null){
            messageDto = new MessageDto(messageMap);
        }

        if(messageDto == null || !messageDto.getReceiverId().equals(receiverId)){
            throw new BusinessException("朋友申请消息不存在");
        }

        if(!Objects.equals(messageDto.getType(), FriendApplicationMessageContent.MESSAGE_TYPE)){
            throw new BusinessException("消息格式错误");
        }

        return messageDto;
    }
}
